// Fill out your copyright notice in the Description page of Project Settings.


#include "DefaultMenu.h"
#include "Components/ListView.h"
#include "MultiplayerSessions.h"
#include "MultiplayerSessionsSubsystem.h"
#include "OnlineSessionSettings.h"
#include "OnlineSubsystemUtils.h"
#include "USessionResultObject.h"
#include "Components/CanvasPanel.h"
#include "Components/CircularThrobber.h"
#include "Components/TextBlock.h"

void UDefaultMenu::MenuSetup(const FString MainPath)
{

	PathToMain = FString::Printf(TEXT("%s?listen"), *MainPath);
	
	// bIsFocusable = true;
	UWorld* World = GetWorld();
	if (World)
	{
		APlayerController* PlayerController = World->GetFirstPlayerController();
		if (PlayerController)
		{
			FInputModeUIOnly InputMode;
			// InputMode.SetWidgetToFocus(TakeWidget());
			InputMode.SetLockMouseToViewportBehavior(EMouseLockMode::DoNotLock);
			PlayerController->SetInputMode(InputMode);
			PlayerController->SetShowMouseCursor(true);
		}
	}

	UGameInstance* GameInstance = GetGameInstance();
	if (GameInstance)
	{
		MultiplayerSessionsSubsystem = GameInstance->GetSubsystem<UMultiplayerSessionsSubsystem>();
	}

	if (MultiplayerSessionsSubsystem)
	{
		MultiplayerSessionsSubsystem->MultiplayerOnCreateSessionComplete.AddUObject(this, &ThisClass::OnCreateSession);
		MultiplayerSessionsSubsystem->MultiplayerOnFindSessionComplete.AddUObject(this, &ThisClass::OnFindSession);
		MultiplayerSessionsSubsystem->MultiplayerOnJoinSessionComplete.AddUObject(this, &ThisClass::OnJoinSession);
	}

	// initialize UI
	ListViewFindSession->SetScrollbarVisibility(ESlateVisibility::Collapsed);
	CanvasFindSession->SetVisibility(ESlateVisibility::Collapsed);
}

bool UDefaultMenu::Initialize()
{
	// MenuSetup();
	
	return Super::Initialize();
	
}

void UDefaultMenu::NativeDestruct()
{
	if (auto World = GetWorld())
	{
		if (APlayerController* PlayerController = World->GetFirstPlayerController())
		{
			FInputModeGameOnly InputMode;
			PlayerController->SetInputMode(InputMode);
			PlayerController->SetShowMouseCursor(false);
		}
	}
	
	Super::NativeDestruct();
}

void UDefaultMenu::OnCreateSession(bool bWasSuccessful) const
{
	UE_LOG(MultiplayerSession, Display, TEXT("onCreateSession %hs"), bWasSuccessful ? "success" : "fail");
	if (bWasSuccessful)
	{
		UWorld* World = GetWorld();
		if (World)
		{
			World->ServerTravel(PathToMain);
		}
	}
	else
	{
		if (GEngine)
		{
			GEngine->AddOnScreenDebugMessage(-1, 10,FColor::Red, "Failed to create session!");
		}
	}
}

void UDefaultMenu::OnFindSession(const TArray<FOnlineSessionSearchResult>& SessionResults, bool bWasSuccessful) const
{
	UE_LOG(MultiplayerSession, Display, TEXT("onFindSession %hs"), bWasSuccessful ? "success" : "fail");
	Loading->SetVisibility(ESlateVisibility::Collapsed);
	if (bWasSuccessful && SessionResults.Num() > 0)
	{
		ListViewFindSession->SetVisibility(ESlateVisibility::Visible);
		ListViewFindSession->ClearListItems();
		for (auto SessionResult : SessionResults)
		{
			auto item = NewObject<UUSessionResultObject>();
			item->SessionSearchResult = SessionResult;
			ListViewFindSession->AddItem(item);
		}
	}
	else
	{
		TextNoResults->SetVisibility(ESlateVisibility::HitTestInvisible);
	}
}

void UDefaultMenu::FindSession()
{
	CanvasFindSession->SetVisibility(ESlateVisibility::Visible);
	ListViewFindSession->SetVisibility(ESlateVisibility::Collapsed);
	TextNoResults->SetVisibility(ESlateVisibility::Collapsed);
	Loading->SetVisibility(ESlateVisibility::HitTestInvisible);

	
	UE_LOG(MultiplayerSession, Display, TEXT("do FindSession"));
	if (MultiplayerSessionsSubsystem)
	{
		MultiplayerSessionsSubsystem->FindSession(100);
	}
	
}

void UDefaultMenu::OnJoinSession(EOnJoinSessionCompleteResult::Type Result) const
{
	if (auto Subsystem = Online::GetSubsystem(GetWorld()))
	{
		IOnlineSessionPtr SessionInterface = Subsystem->GetSessionInterface();
		if (SessionInterface.IsValid())
		{
			FString Address;
			SessionInterface->GetResolvedConnectString(NAME_GameSession, Address);

			if (auto PlayerController = GetGameInstance()->GetFirstLocalPlayerController())
			{
				PlayerController->ClientTravel(Address, TRAVEL_Absolute);
			}
		}
	}
	
}
